﻿#pragma once

#include "df_macro.h"

///输出指定类型的单字或双字版本
#define DF_CHAR(_cType,_cStr) df::CharSelect<_cType>::Text(_cStr,DF_WIDE_C(_cStr))
#define DF_CHAR_UTF(_cType,_cStr) df::CharSelect<_cType>::Text(DF_UTF_TEXT(_cStr),DF_WIDE_C(_cStr))

namespace df
{

	//二进制数据转16进制字串表
	inline unsigned char * GetCharTable()
	{
		static unsigned char CharTable[256] = {
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			1, 2, 3, 4, 5, 6, 7, 8, 9,//字符1-9
			0, 0, 0, 0, 0, 0, 0,
			10, 11, 12, 13, 14, 15,	//A-F
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
			10, 11, 12, 13, 14, 15,	//a-f
		};
		return CharTable;
	}

	//大写转小写字母表
	inline const char * ToLowerCaseTable()
	{
		static unsigned char CharTable[256] = {
			0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22
			, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42
			, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62
			, 63, 64,
			//大写字母范围
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
			'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
			91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
			109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
			125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
			141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
			157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
			173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
			189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
			205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
			221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
			237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
			253, 254, 255,
		};
		return (const char *)CharTable;
	}





	template<class _CT>
	struct CharSelect
	{
	};

	template<>
	struct CharSelect<char>
	{
		static const char * Text(const char * strA, const wchar_t *)
		{
			return strA;
		}

		static char Text(char strA, wchar_t)
		{
			return strA;
		}

		//数字转字符表
		static const char *  GetTable()
		{
			return "0123456789ABCDEF";
		}
	};

	template<>
	struct CharSelect<wchar_t>
	{
		static const wchar_t * Text(const char *, const wchar_t * strW)
		{
			return strW;
		}
		static wchar_t Text(char, wchar_t strW)
		{
			return strW;
		}

		//数字转字符表
		static const  wchar_t *  GetTable()
		{
			return L"0123456789ABCDEF";
		}
	};
}

namespace df
{



	template<typename _CharT>
	struct BaseChar;


	template<typename _CharT>
	struct BasicC
	{
		const _CharT * char_;

		BasicC()
			: char_(DF_CHAR(_CharT, ""))
		{}



		BasicC(const _CharT * str)
			: char_(str)
		{}

		BasicC(const BasicC & str)
			: char_(str.char_)
		{}

		BasicC(const std::basic_string<_CharT> & str)
		{
			char_ = str.c_str();
		}

		BasicC(const BaseChar<_CharT> & str)
		{
			char_ = str.char_;
		}

		_CharT operator [](intptr_t index) const
		{
			DF_ASSERT(index >= 0);
			return char_[index];
		}



	private:
		BasicC& operator=(const BasicC & str)
		{
			char_ = str.char_;
			return *this;
		}

		BasicC& operator=(const std::basic_string<_CharT> & str)
		{
			char_ = str.c_str();
			return *this;
		}
	};



	template<typename _CharT>
	struct BaseChar
	{
		typedef _CharT CType;

		const _CharT * char_;
		intptr_t length_;

		BaseChar()
			: char_(DF_CHAR(_CharT, ""))
			, length_(0)
		{}

		BaseChar(const BaseChar & buf)
			: char_(buf.char_)
			, length_(buf.length_)
		{

		}



		template<class _ChT, size_t _Size, class = typename df::IsContain<_ChT, _CharT>::Type
			, class = typename std::enable_if<std::is_const<_ChT>::value>::type>//只匹配const []类型
			BaseChar(_ChT(&str)[_Size])
			: char_(str)
			, length_(_Size - 1)
		{
				DF_ASSERT(char_ != nullptr);
				DF_ASSERT(length_ >= 0);
			}


		template<class T, class = typename df::IsContain<T, _CharT>::Type>
		BaseChar(T  str)
			// 		BaseChar(const _CharT * str)
		{
			if (str == nullptr)
			{
				char_ = DF_CHAR(_CharT, "");
				length_ = 0;
			}
			else
			{
				char_ = str;
				length_ = std::char_traits<_CharT>::length(char_);
			}
		}

		BaseChar(const _CharT * str, intptr_t len)
			: char_(str)
			, length_(len)
		{
			DF_ASSERT(char_ != nullptr);
			DF_ASSERT(length_ >= 0);
		}


		BaseChar(const std::basic_string<_CharT> & str)
		{
			char_ = str.c_str();
			length_ = str.length();
		}



		_CharT operator [](intptr_t index) const
		{
			DF_ASSERT(index >= 0);
			DF_ASSERT(index <= length_);
			DF_ASSERT(char_ != nullptr);
			return char_[index];
		}

		intptr_t Size() const
		{
			DF_ASSERT(length_ >= 0);
			return length_;
		}

		void SetLength(intptr_t len)
		{
			length_ = len;
		}

		intptr_t size() const
		{
			DF_ASSERT(length_ >= 0);
			return length_;
		}

		intptr_t Length() const
		{
			DF_ASSERT(length_ >= 0);
			return length_;
		}

		intptr_t length() const
		{
			DF_ASSERT(length_ >= 0);
			return length_;
		}

		const _CharT * GetBuffer() const
		{
			DF_ASSERT(char_ != nullptr);
			return char_;
		}

		const _CharT * c_str() const
		{
			DF_ASSERT(char_ != nullptr);
			return char_;
		}

		const _CharT * begin() const
		{
			DF_ASSERT(char_ != nullptr);
			return char_;
		}

		const _CharT * end() const
		{
			DF_ASSERT(char_ != nullptr);
			DF_ASSERT(length_ >= 0);
			return char_ + length_;
		}


		BaseChar& operator=(const std::basic_string<_CharT> & str)
		{
			char_ = str.c_str();
			length_ = str.length();
			return *this;
		}


		//*******************************************
		// Summary : 查找字符c所在位置,没有返回<0
		// Parameter - const CharType * str : 
		// Parameter - CharType c : 
		// Parameter - intptr_t startPos : 起始位置
		// Parameter - bool positive : 正序查找
		// Returns - intptr_t : 位置
		//*******************************************
		static intptr_t Find(const BaseChar & str, _CharT c, intptr_t startPos = 0, bool positive = true)
		{
			if (positive)
			{
				DF_ASSERT(startPos >= 0);
				for (; startPos < str.length_; startPos++)
				{
					if (str.char_[startPos] == c)
						return startPos;
				}
				return -1;
			}
			else
			{
				DF_ASSERT(startPos < str.length_);
				for (; startPos > 0 ; startPos--)
				{
					if (str.char_[startPos] == c)
						return startPos;
				}
				return -1;
			}
		}

		//*******************************************
		// Summary : 判断src从startPos开始是否匹配dest
		//*******************************************
		FORCEINLINE static bool IsMatch(const BaseChar & src, const BaseChar & dest, intptr_t startPos = 0, bool caseSensitive = true)
		{
			if (startPos < 0 || src.length_ - startPos < dest.length_)
				return false;

			for (intptr_t i = 0; i < dest.length_; i++)
			{
				if (!IsCharEqual(src[i + startPos], dest[i],caseSensitive))
					return false;
			}

			return true;
		}

		FORCEINLINE static bool IsCharEqual(char from, char to, bool caseSensitive = true)
		{
			if (caseSensitive)
				return from == to;
			else
				return ToLowerCaseTable()[(int)from] == to;
		}

		FORCEINLINE static bool IsCharEqual(wchar_t from, wchar_t to, bool caseSensitive = true)
		{
			if (caseSensitive)
				return from == to;
			else
			{
				if (from >= L'A' && from <= L'Z')
					from += 32;

				return from == to;
			}

		}

		//*******************************************
		// Summary : 判断字串从startPos开始是否匹配dest
		//*******************************************
		FORCEINLINE bool IsMatch(const BaseChar & dest, intptr_t startPos = 0, bool caseSensitive = true) const
		{
			return IsMatch(*this, dest, startPos, caseSensitive);
		}

		inline intptr_t Find(_CharT c, intptr_t startPos = 0, bool positive = true) const
		{
			return Find(*this, c, startPos, positive);
		}

		inline const _CharT * Find(const BaseChar & str) const
		{
			return Find(*this, str);
		}

		static const char * Find(const BaseChar<char> & fromStr, const BaseChar<char> & findStr)
		{
			return strstr(fromStr.char_, findStr.char_);
		}

		static const wchar_t * Find(const BaseChar<wchar_t> & fromStr, const BaseChar<wchar_t> & findStr)
		{
			return wcsstr(fromStr.char_, findStr.char_);
		}



		//*******************************************
		// Summary : 替换字串的所有指定字符
		// Parameter - CharT * str : 待替换字串
		// Parameter - CharT fromC : 
		// Parameter - CharT toC : 
		// Returns - CharT * : 
		//*******************************************
		static _CharT * Replace(_CharT * str, _CharT fromC, _CharT toC)
		{
			DF_ASSERT(str != nullptr);
			for (; *str; str++)
			{
				if (*str == fromC)
				{
					*str = toC;
					break;
				}
			}
			return str;
		}



		template<class _NumT>
		inline _NumT ToNumber()
		{
			_NumT res = 0;
			StringToDigit(*this, res);
			return res;
		}

		inline int ToInt()
		{
			return ToNumber<int>();
		}


		inline int64_t ToInt64()
		{
			return ToNumber<int64_t>();
		}

		inline uint64_t ToUint64()
		{
			return ToNumber<uint64_t>();
		}

		inline float ToFloat()
		{
			return ToNumber<float>();
		}

		inline double ToDouble()
		{
			return ToNumber<double>();
		}

		static bool IsNumber(_CharT c)
		{
			return (c >= DF_CHAR(_CharT, '0') && c <= DF_CHAR(_CharT, '9')) || c == DF_CHAR(_CharT, '-');
		}

		static bool IsInteger(_CharT c)
		{
			return (c >= DF_CHAR(_CharT, '0') && c <= DF_CHAR(_CharT, '9'));
		}

		static void AddNumber(std::basic_string<_CharT> & toStr, const BaseChar & str)
		{
			for (auto c : str)
			{
				if (IsNumber(c))
					toStr += c;
			}
		}

		//*******************************************
		// Summary : 将二进制数据转为可显示的16进制字符串(0123456789ABCDEF)格式
		// Parameter - const void * fromBuf : 输入数据
		// Parameter - int bufSize : 数据长度
		// Returns - BaseString & : 
		//*******************************************
		inline static void ByteToString(const void * fromBuf, int bufSize, std::basic_string<_CharT>  & toStr_)
		{
			DF_ASSERT(bufSize >= 0);
			auto oldSize = toStr_.length();
			toStr_.resize(oldSize + bufSize * 2);
			for (int i = 0; i < bufSize; i++)
			{
				toStr_[oldSize + i * 2] = df::CharSelect<_CharT>::GetTable()[((uint8_t*)fromBuf)[i] >> 4];
				toStr_[oldSize + i * 2 + 1] = df::CharSelect<_CharT>::GetTable()[((uint8_t*)fromBuf)[i] & 0xF];
			}
		}



		//*******************************************
		// Summary : 将可显示的16进制字符串转为二进制数据
		// Parameter - void * toBuf : 输出数据
		// Parameter - int bufSize : 输出缓冲区长度
		// Returns - BaseString & : 
		//*******************************************
		FORCEINLINE static void StringToByte(const BaseChar & fromStr_, void * toBuf, int bufSize)
		{
			DF_ASSERT(bufSize >= 0);

			for (int i = 0; i < bufSize && i * 2 + 1 < fromStr_.length_; i++)
			{
				((uint8_t*)toBuf)[i] = (df::GetCharTable()[(uint8_t)(fromStr_[i * 2])] << 4)
					| df::GetCharTable()[(uint8_t)(fromStr_[i * 2 + 1])];
			}
		}


		static void SqlFilter(std::basic_string<_CharT> & sql, const BaseChar & para)
		{
			for (auto c : para)
			{
				if (c == DF_CHAR(_CharT, '\''))
					sql += DF_CHAR(_CharT, '\'');
				else if (c == DF_CHAR(_CharT, '\\'))
					sql += DF_CHAR(_CharT, '\\');
				sql += c;
			}
		}

		//************************************
		// Summary : 原地分割字串(替换分割符为\0)
		// Returns - void :
		// Parameter - CharT * str : 待分割字串
		// Parameter - intptr_t bufSize : 字串长度
		// Parameter - Lam cb : 回调函数用于获取结果:void(BaseChar) 或 bool(BaseChar) 返回flase中断分割
		// Parameter - CharT c : 分割符
		//************************************
		template<class Lam>
		static void Split(_CharT * str, intptr_t bufSize, Lam cb, _CharT c = DF_CHAR(_CharT, '\n'))
		{
			if (str == nullptr || bufSize < 0)
			{
				DF_BREAK_POINT_MSG("参数错误!");
				return;
			}
			intptr_t pos = 0;
			intptr_t startPos = 0;
			BaseChar resChar;
			for (; startPos < bufSize; startPos++)
			{
				if (str[startPos] == c)
				{
					resChar.char_ = str + pos;
					resChar.length_ = startPos - pos;
					str[startPos] = 0;
					if (!df::ExecuteFunctor(cb, resChar))
						return;
					pos = startPos + 1;
				}
				else if (str[startPos] == 0)
				{
					break;
				}
			}

			if (startPos > pos)
			{
				resChar.char_ = str + pos;
				resChar.length_ = startPos - pos;
				cb(resChar);
			}
		}



		static bool LessCompare(const BaseChar & cLeft, const BaseChar & cRight)
		{
			return std::char_traits<_CharT>::compare(cLeft.char_, cRight.char_, cLeft.length_) > 0;
		}

		static bool GreaterCompare(const BaseChar &  cLeft, const BaseChar &  cRight)
		{
			return std::char_traits<_CharT>::compare(cLeft.char_, cRight.char_, cLeft.length_) < 0;
		}



		static bool StrCompare(BaseChar cLeft, BaseChar cRight)
		{
			if (cLeft.length_ != cRight.length_)
				return false;

			for (; *cLeft.char_; ++cLeft.char_, ++cRight.char_)
			{
				if (*cLeft.char_ != *cRight.char_)
					return false;
			}
			return (*cRight.char_ == 0);
		}

		friend  bool operator < (const BaseChar & lRight, const BaseChar & cRight)
		{
			return LessCompare(lRight, cRight);
		}

		friend  bool operator > (const BaseChar & lRight, const BaseChar & cRight)
		{
			return GreaterCompare(lRight, cRight);
		}

		bool Equals(const BaseChar &  cLeft)
		{
			return StrCompare(*this, cLeft);
		}

		friend  bool operator == (const BaseChar & lRight, const BaseChar & cRight)
		{
			return StrCompare(lRight, cRight);
		}

		friend  bool operator != (const BaseChar & lRight, const BaseChar & cRight)
		{
			return !StrCompare(lRight, cRight);
		}

		std::basic_string<_CharT> ToString() const
		{
			return std::basic_string<_CharT>(char_, length_);
		}

		void AssignToString(std::basic_string<_CharT> & os) const
		{
			os.assign(char_, length());
		}

		friend inline std::basic_string<_CharT> & operator += (std::basic_string<_CharT> & os, const BaseChar & str)
		{
			return os.append(str.char_, str.length_);
		}


		friend inline std::basic_ostream<_CharT> & operator << (std::basic_ostream<_CharT> & os, const BaseChar & str)
		{
			os << str.char_;
			return os;
		}


		friend inline std::basic_string<_CharT> operator + (const BaseChar & os, const BaseChar & str)
		{
			std::basic_string<_CharT> str2(os.char_, os.length_);
			str2.append(str.char_, str.length_);
			return str2;
		}

		friend inline std::basic_string<_CharT> operator + (const std::basic_string<_CharT> & os, const BaseChar & str)
		{
			std::basic_string<_CharT> str2(os);
			str2.append(str.char_, str.length_);
			return str2;
		}



		friend inline std::basic_string<_CharT> && operator + (std::basic_string<_CharT> && os, const BaseChar & str)
		{
			os.append(str.char_, str.length_);
			return std::move(os);
		}

		friend  bool operator == (const std::basic_string<_CharT> & str, const BaseChar & cRight)
		{
			return StrCompare(str, cRight);;
		}

		friend  bool operator != (const std::basic_string<_CharT> & str, const BaseChar & cRight)
		{
			return !StrCompare(str, cRight);;
		}
	};


	//对const char *的封装,添加了字串长度属性等
	using CC = BaseChar<TCHAR>;
	using CCa = BaseChar<char>;
	using CCw = BaseChar<wchar_t>;




};
